package cn.com.headfree.dictionary.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.WebApplicationContext;

import com.gta.edu.sdk.base.service.impl.BaseServiceImpl;
import com.gta.edu.sdk.common.dto.Page;
import com.gta.edu.sdk.common.dto.TreeDto;
import com.gta.edu.sdk.config.DateJsonValueProcessor;
import com.gta.edu.sdk.config.DateMorpher;
import com.gta.edu.sdk.util.EhCacheUtil;
import com.gta.edu.sdk.util.RedisClusterUtil;
import com.gta.edu.sdk.util.StringUtil;

import cn.com.headfree.base.config.DictConfig;
import cn.com.headfree.base.initdata.InitCacheData;
import cn.com.headfree.dictionary.dao.IDictionaryDao;
import cn.com.headfree.dictionary.entity.TCommonDictionary;
import cn.com.headfree.dictionary.service.IDictionaryService;
import net.sf.json.JSONArray;
import net.sf.json.JsonConfig;
import net.sf.json.util.JSONUtils;

@Service("dictionaryService")
public class DictionaryServiceImpl extends BaseServiceImpl<TCommonDictionary> implements IDictionaryService {

//    private static final Logger log = LogManager.getLogger(DictionaryServiceImpl.class);

    @Autowired
    private IDictionaryDao dictionaryDao;
    @Autowired
    private DictConfig config;
    private Map<String, TreeDto> treeMap = new HashMap<String, TreeDto>();

    @Override
    public List<TCommonDictionary> findAll() {
        return super.findAll(TCommonDictionary.class, true, null, true);
    }

    @Override
    public void findPageDictionaryByPId(String pId, String sysCode, String name, Page<TCommonDictionary> page) {
        dictionaryDao.findPageDictionaryByPId(pId, sysCode, name, page);
    }

    private TreeDto madeTree(String pId, List<TCommonDictionary> list, String sysCode) {
        if (this.treeMap.containsKey(sysCode)) {
            return this.treeMap.get(sysCode);
        }
        List<TCommonDictionary> sysCodeList = this.groupTree(list, sysCode);
        TCommonDictionary pDict = this.getParentDict(pId, list);
        if (pDict == null) {
            return null;
        }
        TreeDto dto = new TreeDto();
        dto.setId(pDict.getId());
        dto.setText(pDict.getName());
        dto.setIconCls("icon-dict-icon");
        dto.setState("open");
        this.writeData(dto, sysCodeList);
        this.treeMap.put(sysCode, dto);
        return dto;
    }

    private TCommonDictionary getParentDict(String pId, List<TCommonDictionary> list) {
        for (TCommonDictionary dict : list) {
            if (dict.getpId().equals(pId)) {
                return dict;
            }
        }
        return null;
    }

    private void writeData(TreeDto pTreeDto, List<TCommonDictionary> dictList) {
        TreeDto dto = null;
        boolean isLeaf = true;
        for (TCommonDictionary dict : dictList) {
            if (pTreeDto.getId().equals(dict.getpId())) {
                dto = new TreeDto();
                dto.setId(dict.getId());
                dto.setText(dict.getName());
                dto.setIconCls("icon-dict-icon");
                dto.setState("closed");
                List<TreeDto> children = pTreeDto.getChildren();
                if (children == null) {
                    children = new ArrayList<TreeDto>();
                }
                children.add(dto);
                pTreeDto.setChildren(children);
                this.writeData(dto, dictList);
                isLeaf = false;
            }
        }
        if (isLeaf) {
            pTreeDto.setState(null);
            pTreeDto.setIconCls("icon-doc");
        }
    }

    private List<TCommonDictionary> groupTree(List<TCommonDictionary> list, String sysCode) {
        List<TCommonDictionary> sysCodeList = new ArrayList<TCommonDictionary>();
        TCommonDictionary dict = null;
        for (int i = 0; i < list.size(); i++) {
            dict = list.get(i);
            if (dict.getSysCode().equals(sysCode)) {
                sysCodeList.add(dict);
            }
        }
        return sysCodeList;
    }

    @Override
    public TreeDto dictTreeList(String pId, String sysCode, WebApplicationContext app) throws Exception {
        String redisData = EhCacheUtil.getValue(this.config.getRedisDictionaryKey());
        if (StringUtil.isNullOrEmpty(redisData)) {
            redisData = RedisClusterUtil.getInstance().getString(this.config.getRedisDictionaryKey());
            if (StringUtil.isNullOrEmpty(redisData)) {
                redisData = InitCacheData.getInstance().initDictionaryData(app);
                if (StringUtil.isNullOrEmpty(redisData)) {
                    throw new Exception("初始化数据字典数据出现了异常，请与管理员联系！");
                }
            } else {
                EhCacheUtil.put(this.config.getRedisDictionaryKey(), redisData);
            }
        }
        JSONArray array = JSONArray.fromObject(redisData);
        JsonConfig cfg = new JsonConfig();
        cfg.registerJsonValueProcessor(Date.class, new DateJsonValueProcessor());
        cfg.setRootClass(TCommonDictionary.class);
        JSONUtils.getMorpherRegistry().registerMorpher(new DateMorpher("yyyy-MM-dd HH:mm:ss"));
        List<TCommonDictionary> list = JSONArray.toList(array, cfg);
        TreeDto dto = this.madeTree(pId, list, sysCode);
        return dto;
    }

    /**
     * 根据父节点的值查询字典表
     *
     * @param parentValue
     * @return
     */
    @Override
    public List<TCommonDictionary> getAllByParentValue(String parentValue) {
        List<TCommonDictionary> dictionaryList = dictionaryDao.getAllByParentValue(parentValue);
        return dictionaryList;
    }

    @Override
    public void cleanCache() throws Exception {
        if (this.treeMap != null) {
            this.treeMap.clear();
        }
    }

    @Override
    public void removeData(String[] deleteIds) throws Exception {
        TCommonDictionary info = null;
        for (String id : deleteIds) {
            info = this.get(TCommonDictionary.class, id);
            info.setDelSign(1);
            this.update(info);
        }
    }

}
